package edu.mtu.citizenscience.mushroommapper.activity.main;

import com.openswimsoftware.orm.model.list.ModelArrayList;
import com.openswimsoftware.orm.model.list.ModelList;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;

import edu.mtu.citizenscience.cs.sdk.uploader.CitsciUploader;
import edu.mtu.citizenscience.cs.sdk.uploader.CitsciUploaderCallback;
import edu.mtu.citizenscience.cs.sdk.uploader.CitsciUploaderError;
import edu.mtu.citizenscience.cs.sdk.uploader.CitsciUploaderProgress;
import edu.mtu.citizenscience.cs.utils.Message;
import edu.mtu.citizenscience.mushroommapper.MMActivity;
import edu.mtu.citizenscience.mushroommapper.activity.R;
import edu.mtu.citizenscience.mushroommapper.activity.main.reports.ReportListAdapter;
import edu.mtu.citizenscience.mushroommapper.model.ModelReport;
/**
 * @author Corbin Uselton <corbinu@cwuselto@mtu.edu>
 * @copyright (c) 2012 MichiganTech <http://www.mtu.edu>
 * @since 1.0
 * 
 * Manage Report Activity which lists all of the current reports
 * and allows reports to be uploaded
 */
public class ManageReportsActivity extends MMActivity {
	// create progress dialog to display the current progress of uploads
	private ProgressDialog uploadProgress = new ProgressDialog();
	// create citsci uploader object for interacting with the uploader service
	private CitsciUploader uploader = new CitsciUploader();
	// create model list to hold the list of reports
	private ModelList<ModelReport> reports;
	
	// hold the most recent progress message, max and update for the progress dialog
	private String progressMessage = "";
	private int progressMax = 0;
	private int progressUpdate = 0;
	
	/**
	 * @since 1.0
	 * 
	 * Call backs for handling status changes from the uploader
	 * Handles errors, progress and completion
	 */
	private CitsciUploaderCallback uploaderCallbacks = new CitsciUploaderCallback()
	{
		/**
		 * Called on progress update from the uploader
		 * 
		 * @param progress - CitsciUploaderProgress - enum for progress status
		 * @param reportNum - int - the number of the current report -1 if none
		 * @param fileNum - int - the number of the current file -1 if none 
		 * @return void
		 */
		public void uploaderProgress(CitsciUploaderProgress progress, int reportNum, int fileNum) 
		{
			// switch over the different progress status and set the progress message
			switch (progress)
			{
				case PROCESSING:
					progressMessage = "Processing reports...";
				break;
				case STARTING:
					progressMessage = "Starting New Upload...";
				break;
				case REPORT:
					progressMessage = "Uploading report number " + reportNum;
				break;
				case FILE:
					progressMessage = "Uploading report " + reportNum + " file " + fileNum;
				break;
				case REPORT_DATA:
					progressMessage = "Uploading report " + reportNum + " data";
				break;
				case COMPLETING:
					progressMessage = "Completing Upload...";
				break;
				case UPLOADED:
					// show a toast of how many reports were uploaded
					Message.showMessage(aq.getContext(), reportNum + " Reports Uploaded");
				break;
			}
			// update the progress dialog with the new status
			updateProgress();
		}
		
		/**
		 * Called on progress max update from the uploader
		 * 
		 * @param max - int - the maximum for the dialogs progress bar
		 * @return void
		 */
		public void uploaderProgressMax(int max) 
		{
			// set the progressbar max
			progressMax = max;
			// update the progress dialog
			updateProgress();
		}
		
		/**
		 * Called on progress update from the uploader
		 * 
		 * @param update - int - the current value for the dialogs progress bar
		 * @return void
		 */
		public void uploaderProgressUpdate(int update) 
		{
			// set the progressbar current value
			progressUpdate = update;
			// update the progress dialog
			updateProgress();
		}

		/**
		 * Called on error from the uploader
		 * 
		 * @param code - CitsciUploaderError - enum for specific error
		 * @return void
		 */
		public void uploaderError(CitsciUploaderError code) 
		{
			// switch over the different error codes and display the appropriate message to the user as a toast
			switch (code)
			{
				case NONE: break;
				case ALREADY_UPLOADING:
					Message.showMessage(ManageReportsActivity.this, "Uploader already uploading please wait");
				break;
				case NOT_LOGGED_IN:
					Message.showMessage(ManageReportsActivity.this, "Please login before uploading");
				break;
				case INVALID_RESPONSE:
					Message.showMessage(ManageReportsActivity.this, "Error: Invalid response from server");
				break;
				case NO_CONNECTION:
					Message.showMessage(ManageReportsActivity.this, "Could not connect to server");
				break;
				case NO_ENTRIES:
					Message.showMessage(ManageReportsActivity.this, "No new reports to upload");
				break;
			}
			// dismiss the upload dialog
			uploadProgress.dismiss();
		}

		/**
		 * Called on error message from the uploader
		 * 
		 * @param message - String - The error message
		 * @return void
		 */
		public void uploaderErrorMessage(String message) 
		{
			// display the error message usually a message from the server
			Message.showMessage(ManageReportsActivity.this, "Error: " + message);
			// dismiss the upload dialog
			uploadProgress.dismiss();
		}

		/**
		 * Called when the upload is complete
		 * 
		 * @param void
		 * @return void
		 */
		public void uploaderUploadComplete() 
		{
			// dismiss the upload dialog
			uploadProgress.dismiss();
		}
		
	};

	/**
	 * Manage Reports Activity creation handler
	 * 
	 * @param   savedInstanceState - Bundle - Bundle with launch info
	 * @return	void
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) 
	{
		super.onCreate(savedInstanceState);
		
		this.setContentView(R.layout.manage_reports_activity);
     	
		// find all the reports and load them into the reports list
        this.reports = new ModelArrayList<ModelReport>(this, ModelReport.class).find();
        
        // set the list adapter to reports list adapter loaded with the reports and set the item click handler
        this.aq.id(R.id.reportList).adapter(new ReportListAdapter(this.aq, this.reports)).itemClicked(this, "onListItemClick");
		
		// check if there are no reports
		if (this.reports.size() > 0)
		{
			// set the click handler for the upload button
			this.aq.id(R.id.upload_button).clicked(this, "uploadReports");
		}
		else
		{
			// hide the upload button
			this.aq.id(R.id.upload_button).gone();
		}
	}
	
	/**
	 * Manage Reports Activity resume handler
	 * 
	 * @param   void
	 * @return	void
	 */
	@Override
	public void onResume()
	{
		super.onResume();
		
		// resume the uploader service with the uploader callbacks
		this.uploader.resume(this, uploaderCallbacks);
	}
	
	/**
	 * Manage Reports Activity pause handler
	 * 
	 * @param   void
	 * @return	void
	 */
	@Override
	public void onPause()
	{
		super.onPause();
		
		// check if the upload progress dialog is showing
		if (this.uploadProgress.isAdded())
		{
			// dismiss the upload dialog
			this.uploadProgress.dismiss();
		}
		
		// pause the upload service
		this.uploader.pause(this);
	}
	
	/**
	 * onListItemClick hander for when one of the reports is clicked
	 * 
	 * @param   parent - AdapterView<?> - The parent view
	 * @param	view - View - The view that was clicked within the ListView
	 * @param	position - int - The position of the view in the list
	 * @param	id - long - The row id of the item that was clicked
	 * @return	void
	 */
	public void onListItemClick(AdapterView<?> parent, View view, int position, long id)
	{
		// get the report from the list based on its position and then get the id from the report model
		long reportId = this.reports.get(position).getId();
		
		// star the find activity passing the id of the selected report
		this.startActivity(new Intent(this, FindActivity.class).putExtra(ModelReport.REPORT_ID, reportId));
	}
	
	/**
	 * Update the upload progress dialog
	 * 
	 * @param   void
	 * @return	void
	 */
	public void updateProgress()
	{
		// make sure the progress dialog is showing, will do nothing if is already showing
		this.uploadProgress.show(this.getSupportFragmentManager(), "dialog");
		// set the max possible progress for the progress bar
		this.uploadProgress.setMax(this.progressMax);
		// set the current progress for the progress bar
		this.uploadProgress.updateProgress(this.progressUpdate);
		// set the progress dialog progress label
		this.uploadProgress.setProgressLabel(this.progressMessage);
	}
	
	/**
	 * onClick handler for the upload button
	 * 
	 * @param   void
	 * @return	void
	 */
	public void uploadReports()
	{
		// start the uploader for the main table
		this.uploader.startUpload("ORM_MODELREPORT");
	}

}
